package javaCode.chapter16.syn;

/**
 * @author 徐州城
 * @version 1.0
 * 使用多线程，模拟三个窗口同时售票 100张
 */
public class SellTicket {
    public static void main(String[] args) {

/*        测试
        SellTicket01 ticket01 = new SellTicket01();
        SellTicket01 ticket02 = new SellTicket01();
        SellTicket01 ticket03 = new SellTicket01();

        //这里会出现超卖现象
        ticket01.start();//启动售票线程
        ticket02.start();
        ticket03.start();

        System.out.println("==使用实现接口方式来售票==");
        SellTicket02 sellTicket02 = new SellTicket02();

        new Thread(sellTicket02).start();//第一个线程
        new Thread(sellTicket02).start();//第二个线程
        new Thread(sellTicket02).start();//第三个线程*/

        SellTicket03 sellTicket03 = new SellTicket03();

        new Thread(sellTicket03).start();//第一个线程
        new Thread(sellTicket03).start();//第二个线程
        new Thread(sellTicket03).start();//第三个线程
    }
}

//实现接口，使用同步方法synchronized实现线程同步
class SellTicket03 implements Runnable{
    private int ticketNum = 100;//让多个线程共享 num
    private boolean loop = true;//控制run方法的变量
    Object object = new Object();

    //同步方法 （静态的）的锁为当前类本身
    //解读：
    //1. public synchronized static void m(){} 锁是加在 SellTicket03.class
    //2. 如果在静态方法中，实现一个同步代码块
    /*
        synchronized (SellTicket03.class) {
            System.out.println("m2()");
        }
     */
    public synchronized static void m(){}
    public static void m2() {
        synchronized (SellTicket03.class) {
            System.out.println("m2()");
        }
    }

    //说明：
    //1. public synchronized void sell(){} 就是一个同步方法
    //2. 这时锁在 this对象
    //3. 也可以在代码块上写 synchronized，同步代码块，互斥锁还是在this对象
    public /*synchronized*/ void sell(){//同步方法，在同一时刻，只能有一个线程来执行run()

        synchronized (/*this*/ object) {
            if (ticketNum <= 0) {
                System.out.println(Thread.currentThread().getName() + " 窗口售票结束...  ");
                this.loop = false;
                return;
            }

            //休眠50毫秒，模拟
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票"
                    + " 剩余票数=" + (--ticketNum));
        }
    }

    @Override
    public void run() {
        while (loop){
            sell();//sell() 是同步方法
        }
    }
}

/*

//使用Thread方式
class SellTicket01 extends Thread{

    private static int ticketNum = 100;//让多个线程共享 num

    @Override
    public void run() {
        while (true){
            if (ticketNum <= 0 ){
                System.out.println(Thread.currentThread().getName() + " 窗口售票结束...");
                break;
            }

            //休眠50毫秒，模拟
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票"
                + " 剩余票数=" + (--ticketNum));
        }
    }
}

//实现接口
class SellTicket02 implements Runnable{

    private int ticketNum = 100;//让多个线程共享 num

    @Override
    public void run() {
        while (true){
            if (ticketNum <= 0 ){
                System.out.println(Thread.currentThread().getName() + " 窗口售票结束... ");
                break;
            }

            //休眠50毫秒，模拟
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票"
                    + " 剩余票数=" + (--ticketNum));
        }
    }
}
*/
